﻿using JinYuan.DataConvertLib;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PLCCommunication.MQTT;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.ServiceProcess;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace WindowsService1
{
    public partial class Service1 : ServiceBase
    {
        private readonly List<Task> _tasks = new List<Task>();
        private readonly CancellationTokenSource _cts = new CancellationTokenSource();

        private PLCWrapper _plcWrapper;
        private MqttClientWrapper mqttClient = null;
        private System.Threading.Timer _periodicTimer;

        private Dictionary<AcquisitionType, CollectionGroupConfig> _collectionGroups;
        private Dictionary<AcquisitionType, Dictionary<string, string>> _plcAddresses;

        private AcquisitionType[] AcqTypes = null;

        private const int ReconnectionInterval = 5000; // 5 seconds
        private const int MaxReconnectAttempts = 3;

        public string PlcIpAddress = "127.0.0.1";
        public int PlcPort = 9600;


        public string MQTTServerAddress = "127.0.0.1";
        public int MQTTServerPort = 1883;
        public string ClientId = "601UPW01";
        //PPM主题
        public string Topic = "EVE/60J/EQP/NEW_PPM/601UPW01";
        //PPM其他数据
        public string Topic1 = "eve/60J/EQP/601UPW01";
        //直角坐标机械臂
        public string LRobotTopic = "EVE/60J/LRobot/601PWM01_LUR01";
        //关节机械臂
        public string JRobotTopic = "EVE/60J/JRobot/601PWM01_STR01";

        public MqttCredential credentials = null;

        public string BU_id = "EVE2BU";
        public string District_id = "QJ";
        public string Factory_id = "60J";
        public string Production_line_id = "MW-601";
        public string Device_name = "601UPW01";

        public int ThreadInterval = 50;
        public static bool SwitchLog = false;

        public Service1()
        {
            InitializeComponent();
            ServiceName = "TestMqttService";
            CanStop = true; // 服务可以被停止
            CanPauseAndContinue = false;
            AutoLog = true;


        }

        protected override void OnStart(string[] args)
        {
            Logger.WriteInfo($"OnStart：服务启动-{DateTime.Now}");
            InitializeConfig();
            _plcWrapper = new PLCWrapper(PlcIpAddress, PlcPort);
            InitializeTask();
            InitializePLC();
            InitializeMQTT();

            Task.Run(() => RunChangeDetectionTaskAsync(_cts.Token));// 启动变化检测任务


            Logger.WriteInfo($"OnStart：服务启动完毕-{DateTime.Now}");
        }

        protected override async void OnStop()
        {
            _cts.Cancel();
            _periodicTimer?.Dispose();
            // 停止 PLC 读取
            if (_plcWrapper != null)
            {
                _plcWrapper.Disconnect();
                Logger.WriteInfo("PLC 通讯停止.");
            }
            if (mqttClient != null)
            {
                await mqttClient.Disconnect();
                Logger.WriteInfo("MQTT 连接已关闭.");
            }
            Logger.WriteInfo("OnStop");
        }

        /// <summary>
        /// 系统配置文件读取
        /// </summary>
        private void InitializeConfig()
        {
            ReadConfigFromXml();
            PlcIpAddress = ConfigurationManager.AppSettings["PlcIpAddress"] ?? "127.0.0.1";
            PlcPort = int.Parse(ConfigurationManager.AppSettings["PlcPort"] ?? "9600");

            MQTTServerAddress = ConfigurationManager.AppSettings["MQTTServerAddress"] ?? "127.0.0.1";
            MQTTServerPort = int.Parse(ConfigurationManager.AppSettings["MQTTServerPort"] ?? "1883");
            ClientId = ConfigurationManager.AppSettings["ClientId"] ?? "601UPW01";

            Topic = ConfigurationManager.AppSettings["Topic"] ?? "EVE/60J/EQP/NEW_PPM/601UPW01";
            Topic1 = ConfigurationManager.AppSettings["Topic1"] ?? "eve/60J/EQP/601UPW01";
            LRobotTopic = ConfigurationManager.AppSettings["LRobotTopic"] ?? "EVE/60J/LRobot/601PWM01_LUR01";
            JRobotTopic = ConfigurationManager.AppSettings["JRobotTopic"] ?? "EVE/60J/JRobot/601PWM01_STR01";

            BU_id = ConfigurationManager.AppSettings["BU_id"] ?? "601UPW01";
            District_id = ConfigurationManager.AppSettings["District_id"] ?? "QJ";
            Factory_id = ConfigurationManager.AppSettings["Factory_id"] ?? "60J";
            Production_line_id = ConfigurationManager.AppSettings["Production_line_id"] ?? "MW-601";
            Device_name = ConfigurationManager.AppSettings["Device_name"] ?? "601UPW01";
            ThreadInterval = int.Parse(ConfigurationManager.AppSettings["ThreadInterval"] ?? "50");
            SwitchLog = bool.Parse(ConfigurationManager.AppSettings["SwitchLog"] ?? "True");
            MqttDataService.BU_id = BU_id;
            MqttDataService.District_id = District_id;
            MqttDataService.Factory_id = Factory_id;
            MqttDataService.Production_line_id = Production_line_id;
            MqttDataService.Device_name = Device_name;
            MqttDataService.Work_Center_id = "601FGE02";

            Logger.WriteInfo("读取系统配置文件成功！");


        }

        private void ReadConfigFromXml()
        {
            try
            {
                var configPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.xml");
                var doc = XDocument.Load(configPath);
                string deviceName = "";
                _plcAddresses = new Dictionary<AcquisitionType, Dictionary<string, string>>();
                _collectionGroups = new Dictionary<AcquisitionType, CollectionGroupConfig>();

                foreach (var deviceElement in doc.Descendants("Device"))
                {
                    var isEnabled = bool.Parse(deviceElement.Attribute("isEnable")?.Value ?? "false");

                    if (isEnabled)
                    {
                        deviceName = deviceElement.Attribute("name")?.Value;

                        foreach (var groupElement in deviceElement.Elements("CollectionGroup"))
                        {
                            var groupName = groupElement.Attribute("name").Value;
                            Logger.WriteInfo($"添加寄存器组类型: {groupName}");

                            var acquisitionType = (AcquisitionType)Enum.Parse(typeof(AcquisitionType), groupName);
                            var groupConfig = new CollectionGroupConfig
                            {
                                Name = groupName,
                                StartAddress = groupElement.Attribute("StartAddress").Value,
                                Length = int.Parse(groupElement.Attribute("length").Value),
                                DefaultDataType = groupElement.Attribute("DataType")?.Value ?? "Short",
                                Types = new Dictionary<string, TypeConfig>()
                            };

                            var groupAddresses = new Dictionary<string, string>();

                            foreach (var typeElement in groupElement.Elements("Type"))
                            {
                                var typeName = typeElement.Attribute("name").Value;
                                var typeAddress = typeElement.Attribute("address")?.Value ?? typeElement.Value;
                                var dataType = typeElement.Attribute("DataType")?.Value ?? groupConfig.DefaultDataType;

                                // 创建TypeConfig对象
                                var typeConfig = new TypeConfig
                                {
                                    Name = typeName,
                                    Address = typeAddress,
                                    DataType = dataType
                                };

                                groupConfig.Types[typeName] = typeConfig;
                                groupAddresses[typeName] = typeAddress;

                                Logger.WriteInfo($"添加类型: {typeName}, 地址: {typeAddress}, 数据类型: {dataType}");
                            }

                            _collectionGroups[acquisitionType] = groupConfig;
                            _plcAddresses[acquisitionType] = groupAddresses;
                        }
                        break; // 只处理第一个启用的Device
                    }
                }

                Logger.WriteInfo($"读取 【{deviceName}】地址文件成功！！！");
            }
            catch (Exception ex)
            {
                Logger.WriteError($"读取配置文件错误: {ex.Message}");
            }
        }




        private static PLCDataType DetermineDataType(string groupName, string dataTypeAttribute)
        {
            if (!string.IsNullOrEmpty(dataTypeAttribute))
            {
                return (PLCDataType)Enum.Parse(typeof(PLCDataType), dataTypeAttribute);
            }
            if (!string.IsNullOrEmpty(groupName))
            {
                AcquisitionType type = (AcquisitionType)Enum.Parse(typeof(AcquisitionType), groupName);
                // 如果 DataType 属性为空，根据组名推断类型
                switch (type)
                {
                    case AcquisitionType.PPM:
                        return PLCDataType.Short;
                    case AcquisitionType.Axis:
                    case AcquisitionType.Cylinder:
                        return PLCDataType.Float;
                    default:
                        throw new ArgumentException($"未知的组名: {groupName}");
                }

            }
            else
            {
                throw new ArgumentException($"未知的组名: {groupName}");
            }
        }


        #region 初始化Task线程，PLC，MQTT
        private void InitializeTask()
        {
            if (_collectionGroups != null && _collectionGroups.Count > 0)
            {
                List<AcquisitionType> typesList = new List<AcquisitionType>();
                foreach (var kvp in _collectionGroups)
                {
                    switch (kvp.Key)
                    {
                        case AcquisitionType.Axis:
                        case AcquisitionType.Cylinder:
                            StartPeriodicTask(); // 启动定时读取任务
                            break;
                        case AcquisitionType.PPM:
                            typesList.Add(kvp.Key);
                            break;
                        default:
                            break;
                    }
                }

                // 将 List 转换为数组
                AcqTypes = typesList.ToArray();

                // 如果需要，你可以在这里使用 types 数组
                if (AcqTypes.Length > 0)
                {
                    Logger.WriteInfo("添加类型: " + string.Join(", ", AcqTypes));
                    // 这里可以添加其他使用 types 数组的逻辑
                }
            }
        }




        private async void InitializePLC()
        {
            try
            {
                bool connected = await _plcWrapper.ConnectAsync();
                if (connected)
                {
                    Logger.WriteInfo("PLC初始化并连接成功.");
                }
                else
                {
                    Logger.WriteInfo("无法连接 PLC.");
                    throw new Exception("PLC 连接失败");
                }
            }
            catch (Exception ex)
            {
                Logger.WriteError($"初始化 PLC 错误: {ex.Message}");
            }
        }

        private async void InitializeMQTT()
        {
            try
            {
                mqttClient = new MqttClientWrapper(MQTTServerAddress, MQTTServerPort, ClientId, credentials); //初始化
                await mqttClient.InitializeAndConnectAsync();//连接MQTT
                SubscribeTopic(Topic);//订阅主题
                SubscribeTopic(Topic1);//订阅主题1
                SubscribeTopic(LRobotTopic);//订阅直角坐标机械臂
                SubscribeTopic(JRobotTopic);//订阅关机机械臂
            }
            catch (Exception ex)
            {
                Logger.WriteError($"连接 MQTT 代理时出错: {ex.Message}");
            }
        }

        /// <summary>
        /// 订阅主题
        /// </summary>
        /// <param name="topicToSubscribe"></param>
        private void SubscribeTopic(string topicToSubscribe)
        {
            mqttClient.OnMessageReceived += (timestamp, topic, message) =>
            {
                //Console.WriteLine($"{timestamp} Topic[{topic}]: {message}");
                //Logger.WriteMqtt($"{timestamp} Topic[{topic}]");
                // 在这里更新你的 UI
            };
            mqttClient.SubscribeMessage(topicToSubscribe, MqttClientWrapper.MessageFormat.Json, true);
        }


        /// <summary>
        /// 类发布消息
        /// </summary>
        /// <param name="publishTopic"></param>
        /// <param name="sendMessage"></param>
        /// <returns></returns>
        private async Task SendMqttAsync(string source, string publishTopic, string type, JObject messageObj)
        {
            try
            {
                if (publishTopic != null)
                {

                    await mqttClient.SendMessageAsync(source, publishTopic, type, messageObj);
                }
            }
            catch (Exception ex)
            {

                Console.WriteLine($"发布信息: {ex.Message}");
            }

        }


        /// <summary>
        /// 字符串发布消息
        /// </summary>
        /// <param name="source"></param>
        /// <param name="publishTopic"></param>
        /// <param name="type"></param>
        /// <param name="messageObj"></param>
        /// <returns></returns>
        private async Task SendMqttAsync(string source, string publishTopic, string type, string messageObj)
        {
            try
            {
                if (publishTopic != null)
                {


                    await mqttClient.SendMessageAsync(source, publishTopic, type, messageObj);
                }
            }
            catch (Exception ex)
            {

                Console.WriteLine($"发布信息: {ex.Message}");
            }

        }
        #endregion


        #region 创建定时线程
        /// <summary>
        /// 轴扭矩定时器采集线程
        /// </summary>
        private void StartPeriodicTask()
        {
            Logger.WriteInfo("启动定期数据收集任务");
            _periodicTimer = new System.Threading.Timer(async _ =>
            {
                try
                {
                    Logger.WriteInfo($"定期触发任务: {DateTime.Now}");
                    await CollectAndPublishData("AxisTask", new[] { AcquisitionType.Axis });
                    await CollectAndPublishData("AxisTask", new[] { AcquisitionType.Cylinder });
                    await CollectAndPublishData("LRobotTask", new[] { AcquisitionType.LRobot });
                    Logger.WriteInfo($"定期任务完成: {DateTime.Now}");
                }
                catch (Exception ex)
                {
                    Logger.WriteError($"周期性任务执行错误: {ex.Message}");
                }
            }, null, TimeSpan.Zero, TimeSpan.FromSeconds(1)); // 每秒执行一次
        }

        /// <summary>
        /// 有变化数据采集线程
        /// </summary>
        /// <param name="workerId"></param>
        /// <param name="ct"></param>
        /// <returns></returns>

        private async Task RunChangeDetectionTaskAsync(CancellationToken ct)
        {
            while (!ct.IsCancellationRequested)
            {
                if (_plcWrapper._plcIsConnected)
                {
                    try
                    {
                        await CollectAndPublishData("ChangeTask", AcqTypes);
                        await Task.Delay(500, ct);
                    }
                    catch (OperationCanceledException)
                    {
                        // 正常取消，无需额外处理
                    }
                    catch (Exception ex)
                    {
                        Logger.WriteError($"变更检测任务错误: {ex.Message}");
                        await Task.Delay(1000, ct);
                    }
                }
            }
        }
        #endregion

        /// <summary>
        /// 读取数据
        /// </summary>
        /// <param name="source"></param>
        /// <param name="addresses"></param>
        /// <returns></returns>
        private async Task CollectAndPublishData(string source, AcquisitionType[] types)
        {
            const int maxRetries = 3;
            for (int retry = 0; retry < maxRetries; retry++)
            {
                try
                {
                    var requests = new List<PLCDataReadRequest>();
                    foreach (var type in types)
                    {
                        var config = _collectionGroups[type];
                        requests.Add(new PLCDataReadRequest
                        {
                            StartAddress = config.StartAddress,
                            Length = (ushort)config.Length,
                            StorageName = config.Name
                        });
                    }

                    foreach (var request in requests)
                    {
                        var result = await _plcWrapper._dataReader.ReadDataAsync(request);
                        if (result.IsSuccess)
                        {
                            await ProcessPLCData(source, request.StorageName, result.Data);
                        }
                        else
                        {
                            Logger.WriteInfo($"错误读取 {result.StorageName}: {result.ErrorMessage}");
                            throw new Exception($"读取 PLC 数据失败: {result.ErrorMessage}");
                        }
                    }
                    break; // 如果成功，退出重试循环
                }
                catch (Exception ex)
                {
                    Logger.WriteError($"Error {source}: {ex.Message}");
                    if (retry < maxRetries - 1)
                    {
                        Logger.WriteInfo($"尝试重新连接到 PLC，尝试 {retry + 1}");
                        bool reconnected = await AttemptReconnection(_cts.Token);
                        if (!reconnected)
                        {
                            Logger.WriteError("无法重新连接 PLC，放弃进一步尝试");
                            break;
                        }
                    }
                    else
                    {
                        Logger.WriteError($"最大重试次数 ({maxRetries}) 已到达，放弃操作");
                    }
                }
            }
        }

        /// <summary>
        /// 重连PLC
        /// </summary>
        /// <param name="ct"></param>
        /// <returns></returns>
        private async Task<bool> AttemptReconnection(CancellationToken ct)
        {
            const int MaxReconnectAttempts = 3;
            const int ReconnectionInterval = 5000; // 5 seconds

            for (int attempt = 1; attempt <= MaxReconnectAttempts; attempt++)
            {
                if (ct.IsCancellationRequested)
                {
                    return false;
                }

                Logger.WriteInfo($"尝试重新连接PLC，第 {attempt} 次尝试");
                bool reconnected = await _plcWrapper.ReconnectAsync();
                if (reconnected)
                {
                    Logger.WriteInfo("PLC重新连接成功");
                    return true;
                }

                if (attempt < MaxReconnectAttempts)
                {
                    await Task.Delay(ReconnectionInterval, ct);
                }
            }
            Logger.WriteError($"PLC重新连接失败，已尝试 {MaxReconnectAttempts} 次");
            return false;
        }


        /// <summary>
        /// 读取PLC数据
        /// </summary>
        /// <param name="source"></param>
        /// <param name="acquisitionTypeName"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        private async Task ProcessPLCData(string source, string acquisitionTypeName, byte[] data)
        {
            try
            {
                AcquisitionType type = (AcquisitionType)Enum.Parse(typeof(AcquisitionType), acquisitionTypeName);
                var typeConfigs = GetTypeConfigs(type).ToList();
                bool hasChanges = false;
                List<StationData> processedValues = null;

                switch (type)
                {
                    case AcquisitionType.PPM:
                        var ppmResult = ProcessShortData(type, data, typeConfigs);
                        hasChanges = ppmResult.hasChanges;
                        processedValues = ppmResult.values;
                        break;

                    case AcquisitionType.Axis:
                    case AcquisitionType.Cylinder:
                    case AcquisitionType.LRobot:
                        var floatResult = ProcessFloatData(type, data, typeConfigs);
                        hasChanges = floatResult.hasChanges;
                        processedValues = floatResult.values;
                        break;

                    default:
                        Logger.WriteError($"未知的采集类型: {type}");
                        return;
                }

                if (hasChanges && processedValues != null)
                {

                    // 上传到MQTT服务器
                    await UpMQTTServerDataNew(source, type, processedValues);
                }
                else
                {
                    Logger.WriteInfo($"{type} 数据未改变，未上传");
                }
            }
            catch (Exception ex)
            {
                Logger.WriteError($"处理 PLC 数据时出错（源: {source}, 类型: {acquisitionTypeName}): {ex.Message}");
            }
        }

        // 相应地，ProcessFloatData方法也需要修改返回类型

        private List<StationData> _lastFloatStationData = new List<StationData>();
        private (bool hasChanges, List<StationData> values) ProcessFloatData(AcquisitionType type, byte[] rawData, List<TypeConfig> typeConfigs)
        {
            bool hasChanges = false;
            var currentValues = new DataValue[typeConfigs.Count];

            // 记录实际需要处理的数据点数量
            Logger.WriteInfo($"开始处理数据: typeConfigs.Count={typeConfigs.Count}, rawData.Length={rawData.Length}");
            var sw = new Stopwatch();
            sw.Restart();
            // 初始化数组为完整的大小
            currentValues = new DataValue[typeConfigs.Count];
            var stationDataList = new List<StationData>();

            try
            {
                // 第一步：处理所有Float类型数据（主数据）
                var floatConfigs = typeConfigs.Where(t => t.DataType.Equals("Float", StringComparison.OrdinalIgnoreCase)).ToList();
                foreach (var config in floatConfigs)
                {
                    // 从地址中提取偏移量
                    if (int.TryParse(config.Address.Substring(1), out int address))
                    {
                        int startAddress = int.Parse(typeConfigs[0].Address.Substring(1));
                        int offset = (address - startAddress) * 2;

                        if (offset >= 0 && offset + 4 <= rawData.Length)
                        {
                            byte[] valueBytes = new byte[4];
                            for (int j = 0; j < 4; j++)
                            {
                                valueBytes[j] = (byte)(Convert.ToInt32(rawData[offset + j]) & 0xFF);
                            }

                            object convertedValue = ConvertFromBytes(valueBytes, "Float");
                            int index = typeConfigs.IndexOf(config);
                            currentValues[index] = new DataValue
                            {
                                Name = config.Name,
                                Value = convertedValue,
                                DataType = config.DataType
                            };
                        }
                    }
                }

                // 第二步：处理所有Short类型数据
                var shortConfigs = typeConfigs.Where(t => t.DataType.Equals("Short", StringComparison.OrdinalIgnoreCase)).ToList();
                foreach (var config in shortConfigs)
                {
                    if (int.TryParse(config.Address.Substring(1), out int address))
                    {
                        int startAddress = int.Parse(typeConfigs[0].Address.Substring(1));
                        int offset = (address - startAddress) * 2;

                        if (offset >= 0 && offset + 2 <= rawData.Length)
                        {
                            byte[] valueBytes = new byte[2];
                            for (int j = 0; j < 2; j++)
                            {
                                valueBytes[j] = (byte)(Convert.ToInt32(rawData[offset + j]) & 0xFF);
                            }

                            object convertedValue = ConvertFromBytes(valueBytes, "Short");
                            int index = typeConfigs.IndexOf(config);
                            currentValues[index] = new DataValue
                            {
                                Name = config.Name,
                                Value = convertedValue,
                                DataType = config.DataType
                            };
                        }
                    }
                }

                // 第三步：组织StationData列表

                foreach (var floatConfig in floatConfigs)
                {
                    string baseName = floatConfig.Name;  // 例如 "S_MagLev"
                    var mainValue = currentValues[typeConfigs.IndexOf(floatConfig)]?.Value;
                    // 先获取MainValue，如果为0则跳过这个工位,暂时不过滤
                    //if (mainValue == null || Convert.ToDouble(mainValue) == 0)
                    //{
                    //    Logger.WriteInfo($"跳过工位 {baseName}: MainValue为0或null");
                    //    continue;
                    //}

                    // 只检查MainValue是否与上一次的值相同，暂时不检查
                    //var lastData = _lastStationData.FirstOrDefault(x => x.Name == baseName);
                    //if (lastData != null)
                    //{
                    //    bool valueEqual = Convert.ToDouble(lastData.MainValue) == Convert.ToDouble(mainValue);

                    //    if (valueEqual)
                    //    {
                    //        Logger.WriteInfo($"跳过工位 {baseName}: 值未变化 当前值:{mainValue}");
                    //        continue;
                    //    }

                    //    Logger.WriteInfo($"工位 {baseName} 数值发生变化: {lastData.MainValue} -> {mainValue}");
                    //}

                    // 创建StationData对象
                    var stationData = new StationData
                    {
                        Name = baseName,
                        MainValue = mainValue,
                        Timestamp = DateTime.Now,
                    };

                    stationDataList.Add(stationData);
                    Logger.WriteInfo($"添加工位数据: {stationData.Name}, 值: {stationData.MainValue}, 时间戳: {stationData.Timestamp:HH:mm:ss.fff}");
                }

                // 检查是否有新数据需要更新
                if (stationDataList.Any())
                {
                    hasChanges = true;  // 如果有数据通过过滤，就表示有变化

                    // 创建深拷贝以避免引用问题
                    _lastFloatStationData = stationDataList.Select(s => new StationData
                    {
                        Name = s.Name,
                        MainValue = s.MainValue,
                        Timestamp = s.Timestamp
                    }).ToList();

                    _lastFloatStationData = stationDataList;//把当前的新数据赋值到旧的集合中


                    //// 记录变化信息
                    //foreach (var newData in stationDataList)
                    //{
                    //    Logger.WriteInfo($"工位 {newData.Name} 更新: 时间戳: {newData.Timestamp:HH:mm:ss.fff}, 值: {newData.MainValue}");
                    //}
                }
                else
                {
                    Logger.WriteInfo("没有发现时间戳变化的数据");
                    hasChanges = false;
                }


                sw.Stop();
                Logger.WriteInfo($"处理结束耗时：{sw.ElapsedMilliseconds}ms");
                return (hasChanges, stationDataList);
            }
            catch (Exception ex)
            {
                Logger.WriteError($"处理数据时出错: {ex.Message}");
                return (false, stationDataList);
            }

        }




        /// <summary>
        /// 检测PPM数据是否有变化
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        private List<StationData> _lastStationData = new List<StationData>();

        private readonly StationDataComparer2 _comparer = new StationDataComparer2();

        private (bool hasChanges, List<StationData> values) ProcessShortData(AcquisitionType type, byte[] rawData, List<TypeConfig> typeConfigs)
        {
            var sw = new Stopwatch();
            sw.Start();
            Logger.WriteInfo($"开始新一轮数据处理");

            try
            {
                var currentStationData = new Dictionary<string, StationData>();
                bool hasNewData = false;

                // 1. 获取所有主值配置（Float类型）
                var mainValueConfigs = typeConfigs
                    .Where(t => string.Equals(t.DataType, "Float", StringComparison.OrdinalIgnoreCase))
                    .OrderBy(t => int.Parse(t.Address.Substring(1)))
                    .ToList();

                Logger.WriteInfo($"找到 {mainValueConfigs.Count} 个Float类型配置");
                foreach (var config in mainValueConfigs)
                {
                    Logger.WriteInfo($"Float配置: {config.Name}, 地址: {config.Address}");
                }

                // 2. 获取所有时间配置（Short类型）
                var timeConfigs = typeConfigs
                    .Where(t => string.Equals(t.DataType, "Short", StringComparison.OrdinalIgnoreCase))
                    .ToList();

                // 3. 首先读取所有工位的当前值和时间戳
                foreach (var mainConfig in mainValueConfigs)
                {
                    string stationName = mainConfig.Name;

                    // 读取主值
                    double? mainValue = ReadFloatValue(mainConfig, rawData, typeConfigs[0].Address);
                    if (mainValue == null || mainValue <= 0)
                    {
                        Logger.WriteInfo($"工位 {stationName} 主值无效: {mainValue}");
                        continue;
                    }

                    // 读取时间组件
                    DateTime timestamp = ReadTimestamp(stationName, timeConfigs, rawData, typeConfigs[0].Address);

                    // 添加到当前数据集合
                    currentStationData[stationName] = new StationData
                    {
                        Name = stationName,
                        MainValue = mainValue,
                        Timestamp = timestamp
                    };

                    Logger.WriteInfo($"读取工位数据: {stationName}, 值: {mainValue}, 时间: {timestamp:HH:mm:ss.fff}");
                }

                // 4. 比较新旧数据，确定是否有变化
                if (currentStationData.Any())
                {
                    if (_lastStationData == null || !_lastStationData.Any())
                    {
                        hasNewData = true;
                        Logger.WriteInfo("首次数据采集，记录所有数据");
                    }
                    else
                    {
                        // 检查每个工位的数据是否有变化
                        foreach (var current in currentStationData.Values)
                        {
                            var lastData = _lastStationData.FirstOrDefault(x => x.Name == current.Name);
                            if (lastData == null)
                            {
                                hasNewData = true;
                                Logger.WriteInfo($"发现新工位数据: {current.Name}");
                                break;
                            }

                            // 检查值和时间戳是否都有变化
                            bool valueChanged = Math.Abs(Convert.ToDouble(lastData.MainValue) - Convert.ToDouble(current.MainValue)) > 0.001;
                            bool timeChanged = Math.Abs((current.Timestamp - lastData.Timestamp).TotalMilliseconds) >= 500;

                            if (valueChanged || timeChanged)
                            {
                                hasNewData = true;
                                Logger.WriteInfo($"工位 {current.Name} 数据发生变化 - 值变化: {valueChanged}, 时间变化: {timeChanged}");
                                break;
                            }
                        }
                    }
                }

                // 5. 如果有新数据，更新最后处理的数据
                var resultList = currentStationData.Values.ToList();
                if (hasNewData)
                {
                    _lastStationData = new List<StationData>(resultList);
                    Logger.WriteInfo($"更新状态数据，数量: {resultList.Count}");
                }

                sw.Stop();
                Logger.WriteInfo($"处理完成，耗时: {sw.ElapsedMilliseconds}ms, 数据点数量: {resultList.Count}, 有变化: {hasNewData}");

                return (hasNewData, resultList);
            }
            catch (Exception ex)
            {
                Logger.WriteError($"数据处理错误: {ex.Message}\n{ex.StackTrace}");
                return (false, new List<StationData>());
            }
        }

        private double? ReadFloatValue(TypeConfig config, byte[] rawData, string baseAddress)
        {
            try
            {
                if (!int.TryParse(config.Address.Substring(1), out int address) ||
                    !int.TryParse(baseAddress.Substring(1), out int startAddress))
                {
                    return null;
                }

                int offset = (address - startAddress) * 2;
                if (offset < 0 || offset + 4 > rawData.Length)
                {
                    return null;
                }

                byte[] valueBytes = new byte[4];
                Array.Copy(rawData, offset, valueBytes, 0, 4);
                var value = ConvertFromBytes(valueBytes, "Float");
                return value != null ? Convert.ToDouble(value) : null;
            }
            catch
            {
                return null;
            }
        }

        private DateTime ReadTimestamp(string stationName, List<TypeConfig> timeConfigs, byte[] rawData, string baseAddress)
        {
            // 获取时间组件配置
            var hourConfig = timeConfigs.FirstOrDefault(t => t.Name == $"{stationName}_Hour");
            var minConfig = timeConfigs.FirstOrDefault(t => t.Name == $"{stationName}_Min");
            var secConfig = timeConfigs.FirstOrDefault(t => t.Name == $"{stationName}_Sec");
            var msecConfig = timeConfigs.FirstOrDefault(t => t.Name == $"{stationName}_MSec");

            // 读取时间值
            int hour = ReadShortValue(hourConfig, rawData, baseAddress);
            int minute = ReadShortValue(minConfig, rawData, baseAddress);
            int second = ReadShortValue(secConfig, rawData, baseAddress);
            int millisecond = ReadShortValue(msecConfig, rawData, baseAddress);

            // 验证时间值
            hour = Math.Min(Math.Max(hour, 0), 23);
            minute = Math.Min(Math.Max(minute, 0), 59);
            second = Math.Min(Math.Max(second, 0), 59);
            millisecond = Math.Min(Math.Max(millisecond, 0), 999);

            // 获取当前时间
            var now = DateTime.Now;

            // 构建读取的时间
            var readTime = new DateTime(
                now.Year,
                now.Month,
                now.Day,
                hour,
                minute,
                second,
                millisecond
            );

            // 如果读取的时间比当前时间大，说明应该是前一天的数据
            if (readTime > now)
            {
                readTime = readTime.AddDays(-1);
                Logger.WriteInfo($"检测到跨天数据，调整日期为前一天: {readTime:yyyy-MM-dd HH:mm:ss.fff}");
            }

            return readTime;
        }

        private int ReadShortValue(TypeConfig config, byte[] rawData, string baseAddress)
        {
            try
            {
                if (config == null || !int.TryParse(config.Address.Substring(1), out int address) ||
                    !int.TryParse(baseAddress.Substring(1), out int startAddress))
                {
                    return 0;
                }

                int offset = (address - startAddress) * 2;
                if (offset < 0 || offset + 2 > rawData.Length)
                {
                    return 0;
                }

                byte[] valueBytes = new byte[2];
                Array.Copy(rawData, offset, valueBytes, 0, 2);
                var value = ConvertFromBytes(valueBytes, "Short");
                return Convert.ToInt32(value);
            }
            catch
            {
                return 0;
            }
        }



        private object ConvertFromBytes(byte[] bytes, string dataType)
        {
            try
            {
                if (bytes == null || bytes.Length == 0)
                    return null;

                switch (dataType.ToLower())
                {
                    case "bool":
                        return BitConverter.ToInt16(bytes, 0) != 0;
                    case "short":
                        return ShortLib.GetShortFromByteArray(bytes, 0, DataFormat.CDAB);
                    case "int":
                        return IntLib.GetIntFromByteArray(bytes, 0, DataFormat.CDAB);
                    case "float":
                        return FloatLib.GetFloatFromByteArray(bytes, 0, DataFormat.CDAB);
                    default:
                        return ShortLib.GetShortFromByteArray(bytes, 0, DataFormat.CDAB);
                }
            }
            catch (Exception ex)
            {
                Logger.WriteError($"转换数据类型失败: {BitConverter.ToString(bytes)} to {dataType}, {ex.Message}");
                return null;
            }
        }



        /// <summary>
        /// 上传MQTT
        /// </summary>
        /// <param name="source"></param>
        /// <param name="type"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task UpMQTTServerDataNew(string source, AcquisitionType type, List<StationData> processedValues)
        {
            try
            {
                if (processedValues == null || processedValues.Count == 0)
                {
                    return;
                }

                //var addresses = _plcAddresses[type];
                //var config = _collectionGroups[type];

                var message = MqttDataService.CreateMqttMessage(source, type, processedValues, _plcAddresses, _collectionGroups);

                if (message != null)
                {
                    var messageJson = JsonConvert.SerializeObject(message, new JsonSerializerSettings
                    {
                        NullValueHandling = NullValueHandling.Ignore,
                        Formatting = Formatting.None
                    });
                    if (type.ToString() == "PPM")
                    {
                        await SendMqttAsync(source, Topic, type.ToString(), messageJson);
                    }
                    else if (type.ToString() == "Axis" || type.ToString() == "Cylinder")
                    {
                        await SendMqttAsync(source, Topic1, type.ToString(), messageJson);
                    }
                }
                if (type.ToString() == "LRobot")
                {
                    var message1 = MqttDataService.LRobotMessage(source, type, processedValues, _plcAddresses, _collectionGroups);
                    if (message1 != null)
                    {
                        var messageJson1 = JsonConvert.SerializeObject(message1, new JsonSerializerSettings
                        {
                            NullValueHandling = NullValueHandling.Ignore,
                            Formatting = Formatting.None
                        });
                        if (type.ToString() == "LRobot")
                        {
                            await SendMqttAsync(source, LRobotTopic, type.ToString(), messageJson1);
                        }
                    }
                }

            }
            catch (Exception ex)
            {
                Logger.WriteError($"方法：上传MQTTServer数据，上传失败: {ex.Message}", ex);
            }
        }




        private List<short> ConvertToShortList(object[] data)
        {
            return data.Select(d => Convert.ToInt16(d)).ToList();
        }

        private List<float> ConvertToFloatList(object[] data)
        {
            return data.Select(d => Convert.ToSingle(d)).ToList();
        }

        // 获取特定类型的数据类型
        public string GetDataType(AcquisitionType acquisitionType, string typeName)
        {
            if (_collectionGroups.TryGetValue(acquisitionType, out var groupConfig))
            {
                if (groupConfig.Types.TryGetValue(typeName, out var typeConfig))
                {
                    return typeConfig.DataType;
                }
            }
            return "Short"; // 默认返回Short类型
        }

        // 获取数据类型的字节大小
        public int GetTypeSize(string dataType)
        {
            switch (dataType.ToLower())
            {
                case "bool":
                    return 2;  // 在PLC中通常用2字节表示
                case "short":
                    return 2;  // 2字节
                case "int":
                    return 4;  // 4字节
                case "float":
                    return 4;  // 4字节
                default:
                    return 2;  // 默认2字节
            }
        }

        // 获取组内所有类型配置
        public IEnumerable<TypeConfig> GetTypeConfigs(AcquisitionType acquisitionType)
        {
            if (_collectionGroups.TryGetValue(acquisitionType, out var groupConfig))
            {
                return groupConfig.Types.Values;
            }
            return Enumerable.Empty<TypeConfig>();
        }


    }


    /// <summary>
    /// 时间转化
    /// </summary>

    public static class DateTimeExtensions
    {
        public static long ToUnixTimeMilliseconds(this DateTime dateTime)
        {
            return (long)(dateTime.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;
        }

        public static long GetUnixTimestamp()
        {
            return (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
        }
    }

    // 辅助类
    public class DataValue
    {
        public string Name { get; set; }
        public object Value { get; set; }
        public string DataType { get; set; }

        public override bool Equals(object obj)
        {
            if (obj is DataValue other)
            {
                if (Value == null && other.Value == null) return true;
                if (Value == null || other.Value == null) return false;

                switch (DataType.ToLower())
                {
                    case "float":
                        if (Value is float f1 && other.Value is float f2)
                            return Math.Abs(f1 - f2) < 0.000001f;
                        break;
                    case "bool":
                        if (Value is bool b1 && other.Value is bool b2)
                            return b1 == b2;
                        break;
                }

                return Value.Equals(other.Value);
            }
            return false;
        }

        public override int GetHashCode()
        {
            return Value?.GetHashCode() ?? 0;
        }
    }
}
